00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _linear_solver_implementation_hpp_
00026 #define _linear_solver_implementation_hpp_
00027
00028 #include <boost/scoped_ptr.hpp>
00029 #include <gridpack/math/linear_solver_interface.hpp>
00030 #include <gridpack/parallel/distributed.hpp>
00031 #include <gridpack/utilities/uncopyable.hpp>
00032 #include <gridpack/configuration/configurable.hpp>
00033
00034 namespace gridpack {
00035 namespace math {
00036
00037
00038
00039
00040 template <typename T, typename I>
00041 class LinearSolverImplementation
00042 : public parallel::Distributed,
00043 public utility::Configurable,
00044 private utility::Uncopyable,
00045 public BaseLinearSolverInterface<T, I>
00046 {
00047 public:
00048
00049 typedef T TheType;
00050 typedef I IdxType;
00051 typedef typename BaseLinearSolverInterface<T, I>::MatrixType MatrixType;
00052 typedef typename BaseLinearSolverInterface<T, I>::VectorType VectorType;
00053
00054
00055 LinearSolverImplementation(MatrixType& A)
00056 : parallel::Distributed(A.communicator()),
00057 utility::Configurable("LinearSolver"),
00058 utility::Uncopyable(),
00059 p_matrix(A),
00060 p_solutionTolerance(1.0e-06),
00061 p_relativeTolerance(p_solutionTolerance),
00062 p_maxIterations(100),
00063 p_doSerial(false),
00064 p_constSerialMatrix(),
00065 p_guessZero(false),
00066 p_serialSolution()
00067 {
00068 }
00069
00070
00071 ~LinearSolverImplementation(void)
00072 {
00073
00074 }
00075
00076 protected:
00077
00078
00079 MatrixType& p_matrix;
00080
00081
00082
00083
00084
00085
00086
00087
00088 double p_solutionTolerance;
00089
00090
00091
00092
00093
00094
00095
00096 double p_relativeTolerance;
00097
00098
00099 int p_maxIterations;
00100
00101
00102 bool p_doSerial;
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 bool p_constSerialMatrix;
00115
00116
00117 mutable boost::scoped_ptr<MatrixType> p_serialMatrix;
00118
00119
00120 mutable boost::scoped_ptr<VectorType> p_serialRHS;
00121
00122
00123 bool p_guessZero;
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 mutable boost::scoped_ptr<VectorType> p_serialSolution;
00136
00137
00138 mutable std::vector<TheType> p_valueBuffer;
00139
00140
00141 void p_configure(utility::Configuration::CursorPtr props)
00142 {
00143 if (props) {
00144 p_solutionTolerance = props->get("SolutionTolerance", p_solutionTolerance);
00145 p_relativeTolerance = props->get("RelativeTolerance", p_relativeTolerance);
00146 p_maxIterations = props->get("MaxIterations", p_maxIterations);
00147
00148 p_doSerial = props->get("ForceSerial", p_doSerial);
00149 p_constSerialMatrix = props->get("SerialMatrixConstant", p_constSerialMatrix);
00150
00151
00152 p_doSerial = (p_doSerial && (this->processor_size() > 1));
00153
00154 p_guessZero = props->get("InitialGuessZero", p_guessZero);
00155 }
00156 }
00157
00158
00159 double p_tolerance(void) const
00160 {
00161 return p_solutionTolerance;
00162 }
00163
00164
00165 void p_tolerance(const double& tol)
00166 {
00167 p_solutionTolerance = tol;
00168 }
00169
00170
00171 int p_maximumIterations(void) const
00172 {
00173 return p_maxIterations;
00174 }
00175
00176
00177 void p_maximumIterations(const int& n)
00178 {
00179 p_maxIterations = n;
00180 }
00181
00182
00183 virtual void p_solveImpl(MatrixType& A, const VectorType& b, VectorType& x) const = 0;
00184
00185
00186 virtual void p_resolveImpl(const VectorType& b, VectorType& x) const = 0;
00187
00188
00189 void p_serialSolvePrep(const VectorType& b, VectorType& x) const
00190 {
00191
00192 if (p_valueBuffer.empty()) {
00193 p_valueBuffer.resize(b.size());
00194 }
00195
00196
00197 if (!p_serialRHS) {
00198 p_serialRHS.reset(b.localClone());
00199 } else {
00200 b.getAllElements(&p_valueBuffer[0]);
00201 p_serialRHS->setElementRange(0, b.size() - 1, &p_valueBuffer[0]);
00202 }
00203
00204
00205 if (!p_serialSolution) {
00206 if (!p_guessZero) {
00207 p_serialSolution.reset(x.localClone());
00208 } else {
00209 p_serialSolution.reset(p_serialRHS->clone());
00210 }
00211 } else {
00212 if (!p_guessZero) {
00213 x.getAllElements(&p_valueBuffer[0]);
00214 p_serialSolution->setElementRange(0, x.size() - 1, &p_valueBuffer[0]);
00215 }
00216 }
00217 }
00218
00219
00220 void p_serialSolutionDist(VectorType& x) const
00221 {
00222 BOOST_ASSERT(!p_valueBuffer.empty());
00223 IdxType lo, hi;
00224 x.localIndexRange(lo, hi);
00225 p_serialSolution->getElementRange(lo, hi, &p_valueBuffer[0]);
00226 x.setElementRange(lo, hi, &p_valueBuffer[0]);
00227 x.ready();
00228 }
00229
00230
00231 void p_solve(const VectorType& b, VectorType& x) const
00232 {
00233 if (p_doSerial) {
00234
00235
00236
00237
00238 if (!p_serialMatrix ) {
00239 p_serialMatrix.reset(p_matrix.localClone());
00240 } else if (!p_constSerialMatrix) {
00241 p_serialMatrix.reset(p_matrix.localClone());
00242 }
00243
00244 this->p_serialSolvePrep(b, x);
00245
00246
00247
00248 this->p_solveImpl(*p_serialMatrix, *p_serialRHS, *p_serialSolution);
00249
00250
00251
00252
00253 this->p_serialSolutionDist(x);
00254
00255
00256 } else {
00257
00258 this->p_solveImpl(p_matrix, b, x);
00259
00260 }
00261 }
00262
00263
00264 void p_resolve(const VectorType& b, VectorType& x) const
00265 {
00266 if (p_doSerial) {
00267
00268 this->p_serialSolvePrep(b, x);
00269
00270
00271
00272 this->p_resolveImpl(*p_serialRHS, *p_serialSolution);
00273
00274
00275
00276
00277 this->p_serialSolutionDist(x);
00278
00279 } else {
00280
00281 this->p_resolveImpl(b, x);
00282
00283 }
00284 }
00285
00286
00287 MatrixType *p_solve(const MatrixType& B) const
00288 {
00289 VectorType b(B.communicator(), B.localRows());
00290 VectorType X(B.communicator(), B.localRows());
00291 MatrixType *result(new MatrixType(B.communicator(), B.localRows(), B.localCols(), Dense));
00292
00293 int ilo, ihi;
00294 X.localIndexRange(ilo, ihi);
00295 int nloc(X.localSize());
00296 std::vector<IdxType> iidx;
00297 iidx.reserve(nloc);
00298 for (IdxType i = ilo; i < ihi; ++i) { iidx.push_back(i); }
00299 std::vector<IdxType> jidx(nloc);
00300 std::vector<TheType> locX(nloc);
00301
00302 for (int j = 0; j < B.cols(); ++j) {
00303 column(B, j, b);
00304 X.zero();
00305 X.ready();
00306 if (j == 0) {
00307 this->solve(b, X);
00308 } else {
00309 this->resolve(b, X);
00310 }
00311 std::fill(jidx.begin(), jidx.end(), j);
00312 X.getElements(nloc, &iidx[0], &locX[0]);
00313 result->setElements(nloc, &iidx[0], &jidx[0], &locX[0]);
00314 }
00315
00316 result->ready();
00317 return result;
00318 }
00319
00320 };
00321
00322 }
00323 }
00324
00325
00326
00327 #endif